//
//  IQKBManager.swift
//  YuanJuBian
//
//  Created by apple on 2022/3/7.
//

import UIKit
#if canImport(IQKeyboardManagerSwift)
import IQKeyboardManagerSwift

protocol PYKeyboardDelegate : UIView{
    
    func viewForKeyboardFrameChange() -> UIView?
    
    func keyboardChange(with transition:PYTextKeyboardTransition)
}

class IQKBManager: NSObject {
    
    static var shared = IQKBManager()
    
    var keyboardFlag = PYTextKeyboardFlag()
    
    weak var keyboardSuperView : PYKeyboardDelegate?

    /// 注册IQKeyboardManager
    class func registerSDK(){
        
        IQKeyboardManager.shared.enable = true
        IQKeyboardManager.shared.shouldResignOnTouchOutside = true
        IQKeyboardManager.shared.enableAutoToolbar = false
        IQKeyboardManager.shared.shouldShowToolbarPlaceholder = false
        UITextField.appearance().inputAccessoryView = UIView()
    }
    
    /// 关闭IQKeyBoardManager管理
    class func closed(){
        
        IQKeyboardManager.shared.enable = false
    }
    
    /// 开启IQKeyBoardManager管理
    class func opened(){
        
        IQKeyboardManager.shared.enable = true
    }
}

extension IQKBManager{
    
    static func registerNotification(){
        
        self.closed()
        
        PYNotificationManager.addNotificationObserver(self.shared, selector: #selector(self.keyboardFrameWillChange(_:)), name: UIResponder.keyboardWillChangeFrameNotification)
        PYNotificationManager.addNotificationObserver(self.shared, selector: #selector(self.keyboardFrameDidChange(_:)), name: UIResponder.keyboardDidChangeFrameNotification)
    }
    static func resignNotification(){
        
        self.opened()
        
        PYNotificationManager.removeNotificationObserver(self)
    }
    @objc private func keyboardFrameWillChange(_ notif:Notification?){
        guard let notif = notif else {
            return
        }
        guard notif.name == UIResponder.keyboardWillChangeFrameNotification else {
            return
        }
        guard let info = notif.userInfo else {
            return
        }
        let beforeValue = info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue
        let afterValue = info[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue
        let curveNumber = info[UIResponder.keyboardAnimationCurveUserInfoKey] as! Int
        let durationNumber = info[UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
        let before: CGRect = beforeValue?.cgRectValue ?? .zero
        let after: CGRect = afterValue?.cgRectValue ?? .zero
        let curve: UIView.AnimationCurve = UIView.AnimationCurve(rawValue: curveNumber)!
        let duration = durationNumber
        // ignore zero end frame
        if (after.size.width <= 0) && (after.size.height <= 0) {
            return
        }
        
        self.keyboardFlag.notificationFromFrame = before
        self.keyboardFlag.notificationToFrame = after
        self.keyboardFlag.notificationDuration = duration
        self.keyboardFlag.notificationCurve = curve
        
        self.keyboardFlag.lastIsNotification = true
    
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(self._notifyAllKeyboardObservers), object: nil)
        perform(#selector(self._notifyAllKeyboardObservers), with: nil, afterDelay: 0, inModes: [.common])
    }
    @objc private func keyboardFrameDidChange(_ notif:Notification?){
        
        guard let notif = notif else {
            return
        }
        guard notif.name == UIResponder.keyboardDidChangeFrameNotification else {
            return
        }
        guard let info = notif.userInfo else {
            return
        }
        let afterValue = info[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue
        let after: CGRect = afterValue?.cgRectValue ?? .zero
        // ignore zero end frame
        if (after.size.width <= 0) && (after.size.height <= 0) {
            return
        }
        self.keyboardFlag.notificationToFrame = after
        self.keyboardFlag.notificationDuration = 0
        self.keyboardFlag.notificationCurve = UIView.AnimationCurve.easeInOut
        
        self.keyboardFlag.lastIsNotification = false
    
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(self._notifyAllKeyboardObservers), object: nil)
        perform(#selector(self._notifyAllKeyboardObservers), with: nil, afterDelay: 0, inModes: [.common])
    }
    
    @objc private func _notifyAllKeyboardObservers(){
        
        guard let keyboardView = self.keyboardSuperView?.viewForKeyboardFrameChange() else {
            return
        }
        let trans = PYTextKeyboardTransition()
        trans.isFinish = !self.keyboardFlag.lastIsNotification
        
        if self.keyboardFlag.fromFrame.size.width == 0 && self.keyboardFlag.fromFrame.height == 0{
            
            self.keyboardFlag.fromFrame.size.width = keyboardView.bounds.size.width
            self.keyboardFlag.fromFrame.size.height = trans.toFrame.size.height
            self.keyboardFlag.fromFrame.origin.x = trans.toFrame.origin.x
            self.keyboardFlag.fromFrame.origin.y = keyboardView.bounds.size.height
        }
        trans.fromFrame = self.keyboardFlag.fromFrame
        
        if self.keyboardFlag.lastIsNotification{
            trans.toFrame = self.keyboardFlag.notificationToFrame
            trans.animationDuration = self.keyboardFlag.notificationDuration
            trans.animationCurve = self.keyboardFlag.notificationCurve
            trans.animationOption = UIView.AnimationOptions(rawValue: UInt(self.keyboardFlag.notificationCurve.rawValue << 16))
        }

        if !trans.toFrame.equalTo(self.keyboardFlag.fromFrame){
            
            self.keyboardSuperView?.keyboardChange(with: trans)
        }
        self.keyboardFlag.fromFrame = trans.toFrame
    }
}
class PYTextKeyboardFlag{
    
    var fromFrame = CGRect.zero
    
    var lastIsNotification = false
    
    var notificationFromFrame = CGRect.zero
    var notificationToFrame = CGRect.zero
    var notificationDuration : TimeInterval = 0
    var notificationCurve = UIView.AnimationCurve.linear
}

public class PYTextKeyboardTransition: NSObject {
    
    @objc public var isFinish = false
    
    ///< Keyboard frame before transition.
    @objc public var fromFrame = CGRect.zero
    
    ///< Keyboard frame after transition.
    @objc public var toFrame = CGRect.zero
    
    ///< Keyboard transition animation duration.
    @objc public var animationDuration: TimeInterval = 0
    
    ///< Keyboard transition animation curve.
    @objc public var animationCurve = UIView.AnimationCurve.easeInOut
    
    ///< Keybaord transition animation option.
    @objc public var animationOption = UIView.AnimationOptions.layoutSubviews
}
#endif
